package org.jawp.persistence;

import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.List;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

public class CustomerDAO {
	static private CustomerDAO dao = null;
	private final DBCollection customerCollection;
	private final OrderDAO orderDAO;
	private int currentId;

	/*************************************
	 *			Constructor
	 * @throws MongoException 
	 * @throws UnknownHostException 
	 *************************************/

	private CustomerDAO(OrderDAO orderDAO) throws UnknownHostException, MongoException { //TODO change to private, add a Singleton constructor
		// connect to mongoDB (ip and port number are optional)
		Mongo mongo = new Mongo();

		// get database from MongoDB,
		// if database doesn't exists, mongoDB will create it automatically
		DB db = mongo.getDB("JAWP_DB");

		// Get collection from MongoDB, database named "Customers"
		// if collection doesn't exists, mongoDB will create it automatically
		customerCollection = db.getCollection("Customers");

		// query the lastest id
		DBCursor cursor = customerCollection.find().sort(new BasicDBObject("id", -1)).limit(1);
		// get the result
		if(cursor.size() == 0)
			currentId = 0;
		else{
			DBObject result = cursor.next();
			currentId = ((Integer)result.get("id")).intValue() + 1;
		}

		this.orderDAO = orderDAO;
	}

	public static CustomerDAO getCustomerDAO(OrderDAO orderDAO) throws UnknownHostException, MongoException {
		if(dao == null){
			dao = new CustomerDAO(orderDAO);
		}
		return dao;
	}

	/*************************************
	 *				Creation
	 *************************************/

	public Customer createNewCustomer(Title title, String firstName, String lastName,
			String adress, String phone, String email) {
		Customer customer = getCustomerBy(); //TODO
		if(customer == null){
			customer = new Customer(currentId, title, firstName, lastName, adress, phone, email);

			// create a document to store key and value
			BasicDBObject document = new BasicDBObject();
			document.put("id", currentId);
			document.put("title", title.getTitle());
			document.put("firstName", firstName);
			document.put("lastName", lastName);
			document.put("address", adress);
			document.put("phone", phone);
			document.put("email", email);

			// save it into collection
			customerCollection.insert(document);

			// increment current id
			currentId++;
		}
		return customer;
	}

	/*************************************
	 *				Getter
	 *************************************/

	public List<Customer> getCustomers() {		 
		// search query
		BasicDBObject searchQuery = new BasicDBObject();

		// query it
		DBCursor cursor = customerCollection.find(searchQuery);

		List<Customer> customers = new LinkedList<Customer>();
		while(cursor.hasNext()){
			DBObject object = cursor.next();
			customers.add(
					new Customer(
							(Integer)object.get("id"),
							Title.valueOf((String)object.get("title")),
							(String)object.get("firstName"),
							(String)object.get("lastName"),
							(String)object.get("address"),
							(String)object.get("phone"),
							(String)object.get("email")
							)
					);
		}
		return customers;
	}

	public Customer getCustomerBy() { //TODO	 
		return null;
	}

	public Customer getCustomerById(int id) {		 
		// search query
		BasicDBObject searchQuery = new BasicDBObject();
		searchQuery.put("id", id);

		// query it
		DBObject object = customerCollection.findOne(searchQuery);

		if(object == null){
			return null;
		}

		return new Customer(
				(Integer)object.get("id"),
				Title.valueOf((String)object.get("title")),
				(String)object.get("firstName"),
				(String)object.get("lastName"),
				(String)object.get("address"),
				(String)object.get("phone"),
				(String)object.get("email")
				);
	}

	/*************************************
	 *				Setter
	 *************************************/

	/*************************************
	 *				Deletion
	 *************************************/

	public void deleteCustomer(int id) {

		BasicDBObject searchQuery = new BasicDBObject();
		searchQuery.put("id", id);

		customerCollection.remove(customerCollection.findOne(searchQuery));

		//TODO : delete associated products in this method or not ? > imply to have a reference on productDAO (only used here)
		// delete associated products
		orderDAO.deleteOrdersByCustomer(id);
	}
}
